home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / hity wydania / Ubuntu 9.10 PL / karmelkowy-koliberek-desktop-9.10-i386-PL.iso / casper / filesystem.squashfs / usr / share / hplip / base / utils.pyc (.txt) < prev    next >
Python Compiled Bytecode  |  2009-10-28  |  50KB  |  1,613 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.6)
  3.  
  4. from __future__ import generators
  5. import sys
  6. import os
  7. import fnmatch
  8. import tempfile
  9. import socket
  10. import struct
  11. import select
  12. import time
  13. import fcntl
  14. import errno
  15. import stat
  16. import string
  17. import commands
  18. import cStringIO
  19. import re
  20. import xml.parsers.expat as expat
  21. import getpass
  22. import locale
  23. import htmlentitydefs
  24.  
  25. try:
  26.     import platform
  27.     platform_avail = True
  28. except ImportError:
  29.     platform_avail = False
  30.  
  31. from g import *
  32. from codes import *
  33. import pexpect
  34. BIG_ENDIAN = 0
  35. LITTLE_ENDIAN = 1
  36.  
  37. def lock(f):
  38.     log.debug('Locking: %s' % f.name)
  39.     
  40.     try:
  41.         fcntl.flock(f.fileno(), fcntl.LOCK_EX | fcntl.LOCK_NB)
  42.         return True
  43.     except (IOError, OSError):
  44.         log.debug('Failed to unlock %s.' % f.name)
  45.         return False
  46.  
  47.  
  48.  
  49. def unlock(f):
  50.     if f is not None:
  51.         log.debug('Unlocking: %s' % f.name)
  52.         
  53.         try:
  54.             fcntl.flock(f.fileno(), fcntl.LOCK_UN)
  55.             os.remove(f.name)
  56.         except (IOError, OSError):
  57.             pass
  58.         except:
  59.             None<EXCEPTION MATCH>(IOError, OSError)
  60.         
  61.  
  62.     None<EXCEPTION MATCH>(IOError, OSError)
  63.  
  64.  
  65. def lock_app(application, suppress_error = False):
  66.     dir = prop.user_dir
  67.     if os.geteuid() == 0:
  68.         dir = '/var'
  69.     elif not os.path.exists(dir):
  70.         os.makedirs(dir)
  71.     
  72.     lock_file = os.path.join(dir, '.'.join([
  73.         application,
  74.         'lock']))
  75.     
  76.     try:
  77.         lock_file_f = open(lock_file, 'w')
  78.     except IOError:
  79.         if not suppress_error:
  80.             log.error('Unable to open %s lock file.' % lock_file)
  81.         
  82.         return (False, None)
  83.  
  84.     if not lock(lock_file_f):
  85.         if not suppress_error:
  86.             log.error('Unable to lock %s. Is %s already running?' % (lock_file, application))
  87.         
  88.         return (False, None)
  89.     return (True, lock_file_f)
  90.  
  91.  
  92. def Translator(frm = '', to = '', delete = '', keep = None):
  93.     allchars = string.maketrans('', '')
  94.     if len(to) == 1:
  95.         to = to * len(frm)
  96.     
  97.     trans = string.maketrans(frm, to)
  98.     if keep is not None:
  99.         delete = allchars.translate(allchars, keep.translate(allchars, delete))
  100.     
  101.     
  102.     def callable(s):
  103.         return s.translate(trans, delete)
  104.  
  105.     return callable
  106.  
  107.  
  108. def to_bool_str(s, default = '0'):
  109.     ''' Convert an arbitrary 0/1/T/F/Y/N string to a normalized string 0/1.'''
  110.     return default
  111.  
  112.  
  113. def to_bool(s, default = False):
  114.     ''' Convert an arbitrary 0/1/T/F/Y/N string to a boolean True/False value.'''
  115.     None if isinstance(s, str) and s else s[0].lower() in ('1', 't', 'y')
  116.     return default
  117.  
  118.  
  119. def walkFiles(root, recurse = True, abs_paths = False, return_folders = False, pattern = '*', path = None):
  120.     if path is None:
  121.         path = root
  122.     
  123.     
  124.     try:
  125.         names = os.listdir(root)
  126.     except os.error:
  127.         raise StopIteration
  128.  
  129.     if not pattern:
  130.         pass
  131.     pattern = '*'
  132.     pat_list = pattern.split(';')
  133.     for name in names:
  134.         fullname = os.path.normpath(os.path.join(root, name))
  135.         for pat in pat_list:
  136.             if fnmatch.fnmatch(name, pat):
  137.                 if return_folders or not os.path.isdir(fullname):
  138.                     pass
  139.                 None if abs_paths else None<EXCEPTION MATCH>ValueError
  140.                 continue
  141.         
  142.         if recurse and os.path.isdir(fullname):
  143.             for f in walkFiles(fullname, recurse, abs_paths, return_folders, pattern, path):
  144.                 yield f
  145.             
  146.     
  147.  
  148.  
  149. def is_path_writable(path):
  150.     return False
  151.  
  152.  
  153. class TextFormatter:
  154.     LEFT = 0
  155.     CENTER = 1
  156.     RIGHT = 2
  157.     
  158.     def __init__(self, colspeclist):
  159.         self.columns = []
  160.         for colspec in colspeclist:
  161.             self.columns.append(Column(**colspec))
  162.         
  163.  
  164.     
  165.     def compose(self, textlist, add_newline = False):
  166.         numlines = 0
  167.         textlist = list(textlist)
  168.         if len(textlist) != len(self.columns):
  169.             log.error('Formatter: Number of text items does not match columns')
  170.             return None
  171.         for text, column in map(None, textlist, self.columns):
  172.             column.wrap(text)
  173.             numlines = max(numlines, len(column.lines))
  174.         
  175.         complines = [
  176.             ''] * numlines
  177.         for ln in range(numlines):
  178.             for column in self.columns:
  179.                 complines[ln] = complines[ln] + column.getline(ln)
  180.             
  181.         
  182.         if add_newline:
  183.             return '\n'.join(complines) + '\n'
  184.         return '\n'.join(complines)
  185.  
  186.  
  187.  
  188. class Column:
  189.     
  190.     def __init__(self, width = 78, alignment = TextFormatter.LEFT, margin = 0):
  191.         self.width = width
  192.         self.alignment = alignment
  193.         self.margin = margin
  194.         self.lines = []
  195.  
  196.     
  197.     def align(self, line):
  198.         if self.alignment == TextFormatter.CENTER:
  199.             return line.center(self.width)
  200.         if self.alignment == TextFormatter.RIGHT:
  201.             return line.rjust(self.width)
  202.         return line.ljust(self.width)
  203.  
  204.     
  205.     def wrap(self, text):
  206.         self.lines = []
  207.         words = []
  208.         for word in text.split():
  209.             if word <= self.width:
  210.                 words.append(word)
  211.                 continue
  212.             for i in range(0, len(word), self.width):
  213.                 words.append(word[i:i + self.width])
  214.             
  215.         
  216.         if not len(words):
  217.             return None
  218.         current = words.pop(0)
  219.         for word in words:
  220.             increment = 1 + len(word)
  221.             if len(current) + increment > self.width:
  222.                 self.lines.append(self.align(current))
  223.                 current = word
  224.                 continue
  225.             len(words)
  226.             current = current + ' ' + word
  227.         
  228.         self.lines.append(self.align(current))
  229.  
  230.     
  231.     def getline(self, index):
  232.         if index < len(self.lines):
  233.             return ' ' * self.margin + self.lines[index]
  234.         return ' ' * (self.margin + self.width)
  235.  
  236.  
  237.  
  238. class Stack:
  239.     
  240.     def __init__(self):
  241.         self.stack = []
  242.  
  243.     
  244.     def pop(self):
  245.         return self.stack.pop()
  246.  
  247.     
  248.     def push(self, value):
  249.         self.stack.append(value)
  250.  
  251.     
  252.     def as_list(self):
  253.         return self.stack
  254.  
  255.     
  256.     def clear(self):
  257.         self.stack = []
  258.  
  259.     
  260.     def __len__(self):
  261.         return len(self.stack)
  262.  
  263.  
  264.  
  265. class Queue(Stack):
  266.     
  267.     def __init__(self):
  268.         Stack.__init__(self)
  269.  
  270.     
  271.     def get(self):
  272.         return self.stack.pop(0)
  273.  
  274.     
  275.     def put(self, value):
  276.         Stack.push(self, value)
  277.  
  278.  
  279.  
  280. class RingBuffer:
  281.     
  282.     def __init__(self, size_max = 50):
  283.         self.max = size_max
  284.         self.data = []
  285.  
  286.     
  287.     def append(self, x):
  288.         '''append an element at the end of the buffer'''
  289.         self.data.append(x)
  290.         if len(self.data) == self.max:
  291.             self.cur = 0
  292.             self.__class__ = RingBufferFull
  293.         
  294.  
  295.     
  296.     def replace(self, x):
  297.         '''replace the last element instead off appending'''
  298.         self.data[-1] = x
  299.  
  300.     
  301.     def get(self):
  302.         ''' return a list of elements from the oldest to the newest'''
  303.         return self.data
  304.  
  305.  
  306.  
  307. class RingBufferFull:
  308.     
  309.     def __init__(self, n):
  310.         pass
  311.  
  312.     
  313.     def append(self, x):
  314.         self.data[self.cur] = x
  315.         self.cur = (self.cur + 1) % self.max
  316.  
  317.     
  318.     def replace(self, x):
  319.         self.cur = (self.cur - 1) % self.max
  320.         self.data[self.cur] = x
  321.         self.cur = (self.cur + 1) % self.max
  322.  
  323.     
  324.     def get(self):
  325.         return self.data[self.cur:] + self.data[:self.cur]
  326.  
  327.  
  328.  
  329. def sort_dict_by_value(d):
  330.     ''' Returns the keys of dictionary d sorted by their values '''
  331.     items = d.items()
  332.     backitems = [ [
  333.         v[1],
  334.         v[0]] for v in items ]
  335.     backitems.sort()
  336.     return [ backitems[i][1] for i in range(0, len(backitems)) ]
  337.  
  338.  
  339. def commafy(val):
  340.     return unicode(locale.format('%d', val, grouping = True))
  341.  
  342.  
  343. def format_bytes(s, show_bytes = False):
  344.     if s < 1024:
  345.         return ''.join([
  346.             commafy(s),
  347.             ' B'])
  348.     if s < s:
  349.         pass
  350.     elif s < 1048576:
  351.         if show_bytes:
  352.             return ''.join([
  353.                 unicode(round(s / 1024, 1)),
  354.                 u' KB (',
  355.                 commafy(s),
  356.                 ')'])
  357.         return ''.join([
  358.             unicode(round(s / 1024, 1)),
  359.             u' KB'])
  360.     elif s < s:
  361.         pass
  362.     elif s < 1073741824:
  363.         if show_bytes:
  364.             return ''.join([
  365.                 unicode(round(s / 1.04858e+06, 1)),
  366.                 u' MB (',
  367.                 commafy(s),
  368.                 ')'])
  369.         return ''.join([
  370.             unicode(round(s / 1.04858e+06, 1)),
  371.             u' MB'])
  372.     elif show_bytes:
  373.         return ''.join([
  374.             unicode(round(s / 1.07374e+09, 1)),
  375.             u' GB (',
  376.             commafy(s),
  377.             ')'])
  378.     s < 1024
  379.     return ''.join([
  380.         unicode(round(s / 1.07374e+09, 1)),
  381.         u' GB'])
  382.  
  383.  
  384. try:
  385.     make_temp_file = tempfile.mkstemp
  386. except AttributeError:
  387.     
  388.     def make_temp_file(suffix = '', prefix = '', dir = '', text = False):
  389.         path = tempfile.mktemp(suffix)
  390.         fd = os.open(path, os.O_RDWR | os.O_CREAT | os.O_EXCL, 448)
  391.         return (os.fdopen(fd, 'w+b'), path)
  392.  
  393.  
  394.  
  395. def which(command, return_full_path = False):
  396.     path = os.getenv('PATH').split(':')
  397.     path.append('/sbin')
  398.     path.append('/usr/sbin')
  399.     path.append('/usr/local/sbin')
  400.     found_path = ''
  401.     for p in path:
  402.         
  403.         try:
  404.             files = os.listdir(p)
  405.         except OSError:
  406.             continue
  407.             continue
  408.  
  409.         if command in files:
  410.             found_path = p
  411.             break
  412.             continue
  413.     
  414.     if return_full_path:
  415.         if found_path:
  416.             return os.path.join(found_path, command)
  417.         return ''
  418.     return_full_path
  419.     return found_path
  420.  
  421.  
  422. class UserSettings(object):
  423.     
  424.     def __init__(self):
  425.         self.load()
  426.  
  427.     
  428.     def loadDefaults(self):
  429.         self.cmd_print = ''
  430.         path = which('hp-print')
  431.         if len(path) > 0:
  432.             self.cmd_print = 'hp-print -p%PRINTER%'
  433.         else:
  434.             path = which('kprinter')
  435.             if len(path) > 0:
  436.                 self.cmd_print = 'kprinter -P%PRINTER% --system cups'
  437.             else:
  438.                 path = which('gtklp')
  439.                 if len(path) > 0:
  440.                     self.cmd_print = 'gtklp -P%PRINTER%'
  441.                 else:
  442.                     path = which('xpp')
  443.                     if len(path) > 0:
  444.                         self.cmd_print = 'xpp -P%PRINTER%'
  445.                     
  446.         self.cmd_scan = ''
  447.         path = which('xsane')
  448.         if len(path) > 0:
  449.             self.cmd_scan = 'xsane -V %SANE_URI%'
  450.         else:
  451.             path = which('kooka')
  452.             if len(path) > 0:
  453.                 self.cmd_scan = 'kooka'
  454.             else:
  455.                 path = which('xscanimage')
  456.                 if len(path) > 0:
  457.                     self.cmd_scan = 'xscanimage'
  458.                 
  459.         path = which('hp-unload')
  460.         if len(path):
  461.             self.cmd_pcard = 'hp-unload -d %DEVICE_URI%'
  462.         else:
  463.             self.cmd_pcard = 'python %HOME%/unload.py -d %DEVICE_URI%'
  464.         path = which('hp-makecopies')
  465.         if len(path):
  466.             self.cmd_copy = 'hp-makecopies -d %DEVICE_URI%'
  467.         else:
  468.             self.cmd_copy = 'python %HOME%/makecopies.py -d %DEVICE_URI%'
  469.         path = which('hp-sendfax')
  470.         if len(path):
  471.             self.cmd_fax = 'hp-sendfax -d %FAX_URI%'
  472.         else:
  473.             self.cmd_fax = 'python %HOME%/sendfax.py -d %FAX_URI%'
  474.         path = which('hp-fab')
  475.         if len(path):
  476.             self.cmd_fab = 'hp-fab'
  477.         else:
  478.             self.cmd_fab = 'python %HOME%/fab.py'
  479.  
  480.     
  481.     def load(self):
  482.         self.loadDefaults()
  483.         log.debug('Loading user settings...')
  484.         self.auto_refresh = to_bool(user_conf.get('refresh', 'enable', '0'))
  485.         
  486.         try:
  487.             self.auto_refresh_rate = int(user_conf.get('refresh', 'rate', '30'))
  488.         except ValueError:
  489.             self.auto_refresh_rate = 30
  490.  
  491.         
  492.         try:
  493.             self.auto_refresh_type = int(user_conf.get('refresh', 'type', '0'))
  494.         except ValueError:
  495.             self.auto_refresh_type = 0
  496.  
  497.         self.cmd_print = user_conf.get('commands', 'prnt', self.cmd_print)
  498.         self.cmd_scan = user_conf.get('commands', 'scan', self.cmd_scan)
  499.         self.cmd_pcard = user_conf.get('commands', 'pcard', self.cmd_pcard)
  500.         self.cmd_copy = user_conf.get('commands', 'cpy', self.cmd_copy)
  501.         self.cmd_fax = user_conf.get('commands', 'fax', self.cmd_fax)
  502.         self.cmd_fab = user_conf.get('commands', 'fab', self.cmd_fab)
  503.         self.debug()
  504.  
  505.     
  506.     def debug(self):
  507.         log.debug('Print command: %s' % self.cmd_print)
  508.         log.debug('PCard command: %s' % self.cmd_pcard)
  509.         log.debug('Fax command: %s' % self.cmd_fax)
  510.         log.debug('FAB command: %s' % self.cmd_fab)
  511.         log.debug('Copy command: %s ' % self.cmd_copy)
  512.         log.debug('Scan command: %s' % self.cmd_scan)
  513.         log.debug('Auto refresh: %s' % self.auto_refresh)
  514.         log.debug('Auto refresh rate: %s' % self.auto_refresh_rate)
  515.         log.debug('Auto refresh type: %s' % self.auto_refresh_type)
  516.  
  517.     
  518.     def save(self):
  519.         log.debug('Saving user settings...')
  520.         user_conf.set('commands', 'prnt', self.cmd_print)
  521.         user_conf.set('commands', 'pcard', self.cmd_pcard)
  522.         user_conf.set('commands', 'fax', self.cmd_fax)
  523.         user_conf.set('commands', 'scan', self.cmd_scan)
  524.         user_conf.set('commands', 'cpy', self.cmd_copy)
  525.         user_conf.set('refresh', 'enable', self.auto_refresh)
  526.         user_conf.set('refresh', 'rate', self.auto_refresh_rate)
  527.         user_conf.set('refresh', 'type', self.auto_refresh_type)
  528.         self.debug()
  529.  
  530.  
  531.  
  532. def no_qt_message_gtk():
  533.     
  534.     try:
  535.         import gtk as gtk
  536.         w = gtk.Window()
  537.         dialog = gtk.MessageDialog(w, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_WARNING, gtk.BUTTONS_OK, 'PyQt not installed. GUI not available. Please check that the PyQt package is installed. Exiting.')
  538.         dialog.run()
  539.         dialog.destroy()
  540.     except ImportError:
  541.         log.error('PyQt not installed. GUI not available. Please check that the PyQt package is installed. Exiting.')
  542.  
  543.  
  544.  
  545. def canEnterGUIMode():
  546.     if not prop.gui_build:
  547.         log.warn('GUI mode disabled in build.')
  548.         return False
  549.     if not os.getenv('DISPLAY'):
  550.         log.warn('No display found.')
  551.         return False
  552.     if not checkPyQtImport():
  553.         log.warn('Qt/PyQt 3 initialization failed.')
  554.         return False
  555.     return True
  556.  
  557.  
  558. def canEnterGUIMode4():
  559.     if not prop.gui_build:
  560.         log.warn('GUI mode disabled in build.')
  561.         return False
  562.     if not os.getenv('DISPLAY'):
  563.         log.warn('No display found.')
  564.         return False
  565.     if not checkPyQtImport4():
  566.         log.warn('Qt/PyQt 4 initialization failed.')
  567.         return False
  568.     return True
  569.  
  570.  
  571. def checkPyQtImport():
  572.     
  573.     try:
  574.         import qt as qt
  575.     except ImportError:
  576.         if os.getenv('DISPLAY') and os.getenv('STARTED_FROM_MENU'):
  577.             no_qt_message_gtk()
  578.         
  579.         log.error('PyQt not installed. GUI not available. Exiting.')
  580.         return False
  581.  
  582.     qtMajor = int(qt.qVersion().split('.')[0])
  583.     if qtMajor < MINIMUM_QT_MAJOR_VER:
  584.         log.error('Incorrect version of Qt installed. Ver. 3.0.0 or greater required.')
  585.         return False
  586.     
  587.     try:
  588.         pyqtVersion = qt.PYQT_VERSION_STR
  589.     except AttributeError:
  590.         qtMajor < MINIMUM_QT_MAJOR_VER
  591.         qtMajor < MINIMUM_QT_MAJOR_VER
  592.         pyqtVersion = qt.PYQT_VERSION
  593.     except:
  594.         qtMajor < MINIMUM_QT_MAJOR_VER
  595.  
  596.     while pyqtVersion.count('.') < 2:
  597.         pyqtVersion += '.0'
  598.         continue
  599.         qtMajor < MINIMUM_QT_MAJOR_VER
  600.     (maj_ver, min_ver, pat_ver) = pyqtVersion.split('.')
  601.     return True
  602.  
  603.  
  604. def checkPyQtImport4():
  605.     
  606.     try:
  607.         import PyQt4 as PyQt4
  608.     except ImportError:
  609.         return False
  610.  
  611.     return True
  612.  
  613.  
  614. try:
  615.     from string import Template
  616. except ImportError:
  617.     
  618.     class _multimap:
  619.         '''Helper class for combining multiple mappings.
  620.  
  621.         Used by .{safe_,}substitute() to combine the mapping and keyword
  622.         arguments.
  623.         '''
  624.         
  625.         def __init__(self, primary, secondary):
  626.             self._primary = primary
  627.             self._secondary = secondary
  628.  
  629.         
  630.         def __getitem__(self, key):
  631.             
  632.             try:
  633.                 return self._primary[key]
  634.             except KeyError:
  635.                 return self._secondary[key]
  636.  
  637.  
  638.  
  639.     
  640.     class _TemplateMetaclass(type):
  641.         pattern = '\n        %(delim)s(?:\n          (?P<escaped>%(delim)s) |   # Escape sequence of two delimiters\n          (?P<named>%(id)s)      |   # delimiter and a Python identifier\n          {(?P<braced>%(id)s)}   |   # delimiter and a braced identifier\n          (?P<invalid>)              # Other ill-formed delimiter exprs\n        )\n        '
  642.         
  643.         def __init__(cls, name, bases, dct):
  644.             super(_TemplateMetaclass, cls).__init__(name, bases, dct)
  645.             if 'pattern' in dct:
  646.                 pattern = cls.pattern
  647.             else:
  648.                 pattern = _TemplateMetaclass.pattern % {
  649.                     'delim': re.escape(cls.delimiter),
  650.                     'id': cls.idpattern }
  651.             cls.pattern = re.compile(pattern, re.IGNORECASE | re.VERBOSE)
  652.  
  653.  
  654.     
  655.     class Template:
  656.         '''A string class for supporting $-substitutions.'''
  657.         __metaclass__ = _TemplateMetaclass
  658.         delimiter = '$'
  659.         idpattern = '[_a-z][_a-z0-9]*'
  660.         
  661.         def __init__(self, template):
  662.             self.template = template
  663.  
  664.         
  665.         def _invalid(self, mo):
  666.             i = mo.start('invalid')
  667.             lines = self.template[:i].splitlines(True)
  668.             if not lines:
  669.                 colno = 1
  670.                 lineno = 1
  671.             else:
  672.                 colno = i - len(''.join(lines[:-1]))
  673.                 lineno = len(lines)
  674.             raise ValueError('Invalid placeholder in string: line %d, col %d' % (lineno, colno))
  675.  
  676.         
  677.         def substitute(self, *args, **kws):
  678.             if len(args) > 1:
  679.                 raise TypeError('Too many positional arguments')
  680.             len(args) > 1
  681.             if not args:
  682.                 mapping = kws
  683.             elif kws:
  684.                 mapping = _multimap(kws, args[0])
  685.             else:
  686.                 mapping = args[0]
  687.             
  688.             def convert(mo):
  689.                 if not mo.group('named'):
  690.                     pass
  691.                 named = mo.group('braced')
  692.                 if named is not None:
  693.                     val = mapping[named]
  694.                     return '%s' % val
  695.                 if mo.group('escaped') is not None:
  696.                     return self.delimiter
  697.                 raise ValueError('Unrecognized named group in pattern', self.pattern)
  698.  
  699.             return self.pattern.sub(convert, self.template)
  700.  
  701.         
  702.         def safe_substitute(self, *args, **kws):
  703.             if len(args) > 1:
  704.                 raise TypeError('Too many positional arguments')
  705.             len(args) > 1
  706.             if not args:
  707.                 mapping = kws
  708.             elif kws:
  709.                 mapping = _multimap(kws, args[0])
  710.             else:
  711.                 mapping = args[0]
  712.             
  713.             def convert(mo):
  714.                 named = mo.group('named')
  715.                 if named is not None:
  716.                     
  717.                     try:
  718.                         return '%s' % mapping[named]
  719.                     except KeyError:
  720.                         return self.delimiter + named
  721.                     
  722.  
  723.                 None<EXCEPTION MATCH>KeyError
  724.                 braced = mo.group('braced')
  725.                 if braced is not None:
  726.                     
  727.                     try:
  728.                         return '%s' % mapping[braced]
  729.                     except KeyError:
  730.                         return self.delimiter + '{' + braced + '}'
  731.                     
  732.  
  733.                 None<EXCEPTION MATCH>KeyError
  734.                 if mo.group('escaped') is not None:
  735.                     return self.delimiter
  736.                 if mo.group('invalid') is not None:
  737.                     return self.delimiter
  738.                 raise ValueError('Unrecognized named group in pattern', self.pattern)
  739.  
  740.             return self.pattern.sub(convert, self.template)
  741.  
  742.  
  743.  
  744.  
  745. def cat(s):
  746.     globals = sys._getframe(1).f_globals.copy()
  747.     if 'self' in globals:
  748.         del globals['self']
  749.     
  750.     locals = sys._getframe(1).f_locals.copy()
  751.     if 'self' in locals:
  752.         del locals['self']
  753.     
  754.     return Template(s).substitute(sys._getframe(1).f_globals, **locals)
  755.  
  756. identity = string.maketrans('', '')
  757. unprintable = identity.translate(identity, string.printable)
  758.  
  759. def printable(s):
  760.     return s.translate(identity, unprintable)
  761.  
  762.  
  763. def any(S, f = (lambda x: x)):
  764.     for x in S:
  765.         if f(x):
  766.             return True
  767.     
  768.     return False
  769.  
  770.  
  771. def all(S, f = (lambda x: x)):
  772.     for x in S:
  773.         if not f(x):
  774.             return False
  775.     
  776.     return True
  777.  
  778. BROWSERS = [
  779.     'firefox',
  780.     'mozilla',
  781.     'konqueror',
  782.     'galeon',
  783.     'skipstone']
  784. BROWSER_OPTS = {
  785.     'firefox': '-new-window',
  786.     'mozilla': '',
  787.     'konqueror': '',
  788.     'galeon': '-w',
  789.     'skipstone': '' }
  790.  
  791. def find_browser():
  792.     if platform_avail and platform.system() == 'Darwin':
  793.         return 'open'
  794.     for b in BROWSERS:
  795.         if which(b):
  796.             return b
  797.     else:
  798.         return None
  799.     return which(b)
  800.  
  801.  
  802. def openURL(url, use_browser_opts = True):
  803.     if platform_avail and platform.system() == 'Darwin':
  804.         cmd = 'open "%s"' % url
  805.         log.debug(cmd)
  806.         os.system(cmd)
  807.     else:
  808.         for b in BROWSERS:
  809.             bb = which(b)
  810.             if bb:
  811.                 bb = os.path.join(bb, b)
  812.                 if use_browser_opts:
  813.                     cmd = '%s %s "%s" &' % (bb, BROWSER_OPTS[b], url)
  814.                 else:
  815.                     cmd = '%s "%s" &' % (bb, url)
  816.                 log.debug(cmd)
  817.                 os.system(cmd)
  818.                 break
  819.                 continue
  820.         
  821.  
  822.  
  823. def uniqueList(input):
  824.     temp = []
  825.     _[1]
  826.     return temp
  827.  
  828.  
  829. def list_move_up(l, m, cmp = None):
  830.     for i in range(1, len(l)):
  831.         if f(i):
  832.             l[i - 1] = l[i]
  833.             l[i] = l[i - 1]
  834.             continue
  835.         None if cmp is None else (None, None, None)
  836.     
  837.  
  838.  
  839. def list_move_down(l, m, cmp = None):
  840.     for i in range(len(l) - 2, -1, -1):
  841.         if f(i):
  842.             l[i] = l[i + 1]
  843.             l[i + 1] = l[i]
  844.             continue
  845.         None if cmp is None else (None, None, None)
  846.     
  847.  
  848.  
  849. class XMLToDictParser:
  850.     
  851.     def __init__(self):
  852.         self.stack = []
  853.         self.data = { }
  854.         self.last_start = ''
  855.  
  856.     
  857.     def startElement(self, name, attrs):
  858.         self.stack.append(unicode(name).lower())
  859.         self.last_start = unicode(name).lower()
  860.         if len(attrs):
  861.             for a in attrs:
  862.                 self.stack.append(unicode(a).lower())
  863.                 self.addData(attrs[a])
  864.                 self.stack.pop()
  865.             
  866.         
  867.  
  868.     
  869.     def endElement(self, name):
  870.         if name.lower() == self.last_start:
  871.             self.addData('')
  872.         
  873.         self.stack.pop()
  874.  
  875.     
  876.     def charData(self, data):
  877.         data = unicode(data).strip()
  878.         if data and self.stack:
  879.             self.addData(data)
  880.         
  881.  
  882.     
  883.     def addData(self, data):
  884.         self.last_start = ''
  885.         
  886.         try:
  887.             data = int(data)
  888.         except ValueError:
  889.             data = unicode(data)
  890.  
  891.         stack_str = '-'.join(self.stack)
  892.         stack_str_0 = '-'.join([
  893.             stack_str,
  894.             '0'])
  895.         
  896.         try:
  897.             self.data[stack_str]
  898.         except KeyError:
  899.             
  900.             try:
  901.                 self.data[stack_str_0]
  902.             except KeyError:
  903.                 self.data[stack_str] = data
  904.  
  905.             j = 2
  906.             while True:
  907.                 
  908.                 try:
  909.                     self.data['-'.join([
  910.                         stack_str,
  911.                         unicode(j)])]
  912.                 except KeyError:
  913.                     self.data['-'.join([
  914.                         stack_str,
  915.                         unicode(j)])] = data
  916.                     break
  917.  
  918.                 j += 1
  919.  
  920.         self.data[stack_str_0] = self.data[stack_str]
  921.         self.data['-'.join([
  922.             stack_str,
  923.             '1'])] = data
  924.         del self.data[stack_str]
  925.  
  926.     
  927.     def parseXML(self, text):
  928.         parser = expat.ParserCreate()
  929.         parser.StartElementHandler = self.startElement
  930.         parser.EndElementHandler = self.endElement
  931.         parser.CharacterDataHandler = self.charData
  932.         parser.Parse(text.encode('utf-8'), True)
  933.         return self.data
  934.  
  935.  
  936.  
  937. def dquote(s):
  938.     return ''.join([
  939.         '"',
  940.         s,
  941.         '"'])
  942.  
  943. if sys.hexversion < 33686512:
  944.     
  945.     def xlstrip(s, chars = ' '):
  946.         i = 0
  947.         for c, i in zip(s, range(len(s))):
  948.             if c not in chars:
  949.                 break
  950.                 continue
  951.         
  952.         return s[i:]
  953.  
  954.     
  955.     def xrstrip(s, chars = ' '):
  956.         return xreverse(xlstrip(xreverse(s), chars))
  957.  
  958.     
  959.     def xreverse(s):
  960.         l = list(s)
  961.         l.reverse()
  962.         return ''.join(l)
  963.  
  964.     
  965.     def xstrip(s, chars = ' '):
  966.         return xreverse(xlstrip(xreverse(xlstrip(s, chars)), chars))
  967.  
  968. else:
  969.     xlstrip = string.lstrip
  970.     xrstrip = string.rstrip
  971.     xstrip = string.strip
  972.  
  973. def getBitness():
  974.     if platform_avail:
  975.         return int(platform.architecture()[0][:-3])
  976.     return struct.calcsize('P') << 3
  977.  
  978.  
  979. def getProcessor():
  980.     if platform_avail:
  981.         return platform.machine().replace(' ', '_').lower()
  982.     return 'i686'
  983.  
  984.  
  985. def getEndian():
  986.     if sys.byteorder == 'big':
  987.         return BIG_ENDIAN
  988.     return LITTLE_ENDIAN
  989.  
  990.  
  991. def get_password():
  992.     return getpass.getpass('Enter password: ')
  993.  
  994.  
  995. def run(cmd, log_output = True, password_func = get_password, timeout = 1):
  996.     output = cStringIO.StringIO()
  997.     
  998.     try:
  999.         child = pexpect.spawn(cmd, timeout = timeout)
  1000.     except pexpect.ExceptionPexpect:
  1001.         return (-1, '')
  1002.  
  1003.     
  1004.     try:
  1005.         while True:
  1006.             update_spinner()
  1007.             i = child.expect([
  1008.                 '[pP]assword:',
  1009.                 pexpect.EOF,
  1010.                 pexpect.TIMEOUT])
  1011.             if child.before:
  1012.                 output.write(child.before)
  1013.                 if log_output:
  1014.                     log.debug(child.before)
  1015.                 
  1016.             
  1017.             if i == 0:
  1018.                 if password_func is not None:
  1019.                     child.sendline(password_func())
  1020.                 else:
  1021.                     child.sendline(get_password())
  1022.             password_func is not None
  1023.             if i == 1:
  1024.                 break
  1025.                 continue
  1026.             if i == 2:
  1027.                 continue
  1028.                 continue
  1029.     except Exception:
  1030.         e = None
  1031.         log.error('Exception: %s' % e)
  1032.  
  1033.     cleanup_spinner()
  1034.     child.close()
  1035.     return (child.exitstatus, output.getvalue())
  1036.  
  1037.  
  1038. def expand_range(ns):
  1039.     '''Credit: Jean Brouwers, comp.lang.python 16-7-2004
  1040.        Convert a string representation of a set of ranges into a
  1041.        list of ints, e.g.
  1042.        u"1-4, 7, 9-12" --> [1,2,3,4,7,9,10,11,12]
  1043.     '''
  1044.     fs = []
  1045.     for n in ns.split(u','):
  1046.         n = n.strip()
  1047.         r = n.split('-')
  1048.         if len(r) == 2:
  1049.             h = r[0].rstrip(u'0123456789')
  1050.             r[0] = r[0][len(h):]
  1051.             if not r[0] and r[1]:
  1052.                 raise ValueError, 'empty range: ' + n
  1053.             r[1]
  1054.             r = [ int(i, 10) for i in r ]
  1055.             if r[0] > r[1]:
  1056.                 raise ValueError, 'bad range: ' + n
  1057.             r[0] > r[1]
  1058.             for i in range(r[0], r[1] + 1):
  1059.                 fs.append(h % i)
  1060.             
  1061.         []
  1062.         fs.append(n)
  1063.     
  1064.     fs = []([ (n, i) for i, n in enumerate(fs) ]).keys()
  1065.     fs = _[4]
  1066.     fs.sort()
  1067.     return fs
  1068.  
  1069.  
  1070. def collapse_range(x):
  1071.     ''' Convert a list of integers into a string
  1072.         range representation:
  1073.         [1,2,3,4,7,9,10,11,12] --> u"1-4,7,9-12"
  1074.     '''
  1075.     if not x:
  1076.         return ''
  1077.     s = [
  1078.         str(x[0])]
  1079.     c = x[0]
  1080.     r = False
  1081.     for i in x[1:]:
  1082.         if i == c + 1:
  1083.             r = True
  1084.         elif r:
  1085.             s.append(u'-%s,%s' % (c, i))
  1086.             r = False
  1087.         else:
  1088.             s.append(u',%s' % i)
  1089.         c = i
  1090.     
  1091.     if r:
  1092.         s.append(u'-%s' % i)
  1093.     
  1094.     return ''.join(s)
  1095.  
  1096.  
  1097. def createSequencedFilename(basename, ext, dir = None, digits = 3):
  1098.     if dir is None:
  1099.         dir = os.getcwd()
  1100.     
  1101.     m = 0
  1102.     for f in walkFiles(dir, recurse = False, abs_paths = False, return_folders = False, pattern = '*', path = None):
  1103.         (r, e) = os.path.splitext(f)
  1104.         if r.startswith(basename) and ext == e:
  1105.             
  1106.             try:
  1107.                 i = int(r[len(basename):])
  1108.             except ValueError:
  1109.                 continue
  1110.  
  1111.             m = max(m, i)
  1112.             continue
  1113.     
  1114.     return os.path.join(dir, '%s%0*d%s' % (basename, digits, m + 1, ext))
  1115.  
  1116.  
  1117. def validate_language(lang, default = 'en_US'):
  1118.     if lang is None:
  1119.         (loc, encoder) = locale.getdefaultlocale()
  1120.     else:
  1121.         lang = lang.lower().strip()
  1122.         for loc, ll in supported_locales.items():
  1123.             if lang in ll:
  1124.                 break
  1125.                 continue
  1126.         else:
  1127.             loc = 'en_US'
  1128.     return loc
  1129.  
  1130.  
  1131. def gen_random_uuid():
  1132.     
  1133.     try:
  1134.         import uuid as uuid
  1135.         return str(uuid.uuid4())
  1136.     except ImportError:
  1137.         uuidgen = which('uuidgen')
  1138.         if uuidgen:
  1139.             uuidgen = os.path.join(uuidgen, 'uuidgen')
  1140.             return commands.getoutput(uuidgen)
  1141.         return ''
  1142.     except:
  1143.         uuidgen
  1144.  
  1145.  
  1146.  
  1147. class RestTableFormatter(object):
  1148.     
  1149.     def __init__(self, header = None):
  1150.         self.header = header
  1151.         self.rows = []
  1152.  
  1153.     
  1154.     def add(self, row_data):
  1155.         self.rows.append(row_data)
  1156.  
  1157.     
  1158.     def output(self, w):
  1159.         if self.rows:
  1160.             num_cols = len(self.rows[0])
  1161.             for r in self.rows:
  1162.                 if len(r) != num_cols:
  1163.                     log.error('Invalid number of items in row: %s' % r)
  1164.                     return None
  1165.             
  1166.             if len(self.header) != num_cols:
  1167.                 log.error('Invalid number of items in header.')
  1168.             
  1169.             col_widths = []
  1170.             for x, c in enumerate(self.header):
  1171.                 max_width = len(c)
  1172.                 for r in self.rows:
  1173.                     max_width = max(max_width, len(r[x]))
  1174.                 
  1175.                 col_widths.append(max_width + 2)
  1176.             
  1177.             x = '+'
  1178.             for c in col_widths:
  1179.                 x = ''.join([
  1180.                     x,
  1181.                     '-' * (c + 2),
  1182.                     '+'])
  1183.             
  1184.             x = ''.join([
  1185.                 x,
  1186.                 '\n'])
  1187.             w.write(x)
  1188.             if self.header:
  1189.                 x = '|'
  1190.                 for i, c in enumerate(col_widths):
  1191.                     x = ''.join([
  1192.                         x,
  1193.                         ' ',
  1194.                         self.header[i],
  1195.                         ' ' * (c + 1 - len(self.header[i])),
  1196.                         '|'])
  1197.                 
  1198.                 x = ''.join([
  1199.                     x,
  1200.                     '\n'])
  1201.                 w.write(x)
  1202.                 x = '+'
  1203.                 for c in col_widths:
  1204.                     x = ''.join([
  1205.                         x,
  1206.                         '=' * (c + 2),
  1207.                         '+'])
  1208.                 
  1209.                 x = ''.join([
  1210.                     x,
  1211.                     '\n'])
  1212.                 w.write(x)
  1213.             
  1214.             for j, r in enumerate(self.rows):
  1215.                 x = '|'
  1216.                 for i, c in enumerate(col_widths):
  1217.                     x = ''.join([
  1218.                         x,
  1219.                         ' ',
  1220.                         self.rows[j][i],
  1221.                         ' ' * (c + 1 - len(self.rows[j][i])),
  1222.                         '|'])
  1223.                 
  1224.                 x = ''.join([
  1225.                     x,
  1226.                     '\n'])
  1227.                 w.write(x)
  1228.                 x = '+'
  1229.                 for c in col_widths:
  1230.                     x = ''.join([
  1231.                         x,
  1232.                         '-' * (c + 2),
  1233.                         '+'])
  1234.                 
  1235.                 x = ''.join([
  1236.                     x,
  1237.                     '\n'])
  1238.                 w.write(x)
  1239.             
  1240.         else:
  1241.             log.error('No data rows')
  1242.  
  1243.  
  1244.  
  1245. def mixin(cls):
  1246.     import inspect as inspect
  1247.     locals = inspect.stack()[1][0].f_locals
  1248.     if '__module__' not in locals:
  1249.         raise TypeError('Must call mixin() from within class def.')
  1250.     '__module__' not in locals
  1251.     dict = cls.__dict__.copy()
  1252.     dict.pop('__doc__', None)
  1253.     dict.pop('__module__', None)
  1254.     locals.update(dict)
  1255.  
  1256. USAGE_OPTIONS = ('[OPTIONS]', '', 'heading', False)
  1257. USAGE_LOGGING1 = ('Set the logging level:', '-l<level> or --logging=<level>', 'option', False)
  1258. USAGE_LOGGING2 = ('', '<level>: none, info\\*, error, warn, debug (\\*default)', 'option', False)
  1259. USAGE_LOGGING3 = ('Run in debug mode:', '-g (same as option: -ldebug)', 'option', False)
  1260. USAGE_LOGGING_PLAIN = ('Output plain text only:', '-t', 'option', False)
  1261. USAGE_ARGS = ('[PRINTER|DEVICE-URI]', '', 'heading', False)
  1262. USAGE_ARGS2 = ('[PRINTER]', '', 'heading', False)
  1263. USAGE_DEVICE = ('To specify a device-URI:', '-d<device-uri> or --device=<device-uri>', 'option', False)
  1264. USAGE_PRINTER = ('To specify a CUPS printer:', '-p<printer> or --printer=<printer>', 'option', False)
  1265. USAGE_BUS1 = ('Bus to probe (if device not specified):', '-b<bus> or --bus=<bus>', 'option', False)
  1266. USAGE_BUS2 = ('', '<bus>: cups\\*, usb\\*, net, bt, fw, par\\* (\\*defaults) (Note: bt and fw not supported in this release.)', 'option', False)
  1267. USAGE_HELP = ('This help information:', '-h or --help', 'option', True)
  1268. USAGE_SPACE = ('', '', 'space', False)
  1269. USAGE_EXAMPLES = ('Examples:', '', 'heading', False)
  1270. USAGE_NOTES = ('Notes:', '', 'heading', False)
  1271. USAGE_STD_NOTES1 = ('If device or printer is not specified, the local device bus is probed and the program enters interactive mode.', '', 'note', False)
  1272. USAGE_STD_NOTES2 = ('If -p\\* is specified, the default CUPS printer will be used.', '', 'note', False)
  1273. USAGE_SEEALSO = ('See Also:', '', 'heading', False)
  1274. USAGE_LANGUAGE = ('Set the language:', '-q <lang> or --lang=<lang>. Use -q? or --lang=? to see a list of available language codes.', 'option', False)
  1275. USAGE_LANGUAGE2 = ('Set the language:', '--lang=<lang>. Use --lang=? to see a list of available language codes.', 'option', False)
  1276. USAGE_MODE = ('[MODE]', '', 'header', False)
  1277. USAGE_NON_INTERACTIVE_MODE = ('Run in non-interactive mode:', '-n or --non-interactive', 'option', False)
  1278. USAGE_GUI_MODE = ('Run in graphical UI mode:', '-u or --gui (Default)', 'option', False)
  1279. USAGE_INTERACTIVE_MODE = ('Run in interactive mode:', '-i or --interactive', 'option', False)
  1280. if sys_conf.get('configure', 'ui-toolkit', 'qt3') == 'qt3':
  1281.     USAGE_USE_QT3 = ('Use Qt3:', '--qt3 (Default)', 'option', False)
  1282.     USAGE_USE_QT4 = ('Use Qt4:', '--qt4', 'option', False)
  1283. else:
  1284.     USAGE_USE_QT3 = ('Use Qt3:', '--qt3', 'option', False)
  1285.     USAGE_USE_QT4 = ('Use Qt4:', '--qt4 (Default)', 'option', False)
  1286.  
  1287. def ttysize():
  1288.     ln1 = commands.getoutput('stty -a').splitlines()[0]
  1289.     vals = {
  1290.         'rows': None,
  1291.         'columns': None }
  1292.     for ph in ln1.split(';'):
  1293.         x = ph.split()
  1294.         if len(x) == 2:
  1295.             vals[x[0]] = x[1]
  1296.             vals[x[1]] = x[0]
  1297.             continue
  1298.     
  1299.     
  1300.     try:
  1301.         rows = int(vals['rows'])
  1302.         cols = int(vals['columns'])
  1303.     except TypeError:
  1304.         (rows, cols) = (25, 80)
  1305.  
  1306.     return (rows, cols)
  1307.  
  1308.  
  1309. def usage_formatter(override = 0):
  1310.     (rows, cols) = ttysize()
  1311.     if override:
  1312.         col1 = override
  1313.         col2 = cols - col1 - 8
  1314.     else:
  1315.         col1 = int(cols / 3) - 8
  1316.         col2 = cols - col1 - 8
  1317.     return TextFormatter(({
  1318.         'width': col1,
  1319.         'margin': 2 }, {
  1320.         'width': col2,
  1321.         'margin': 2 }))
  1322.  
  1323.  
  1324. def format_text(text_list, typ = 'text', title = '', crumb = '', version = ''):
  1325.     '''
  1326.     Format usage text in multiple formats:
  1327.         text: for --help in the console
  1328.         rest: for conversion with rst2web for the website
  1329.         man: for manpages
  1330.     '''
  1331.     if typ == 'text':
  1332.         formatter = usage_formatter()
  1333.         for line in text_list:
  1334.             (text1, text2, format, trailing_space) = line
  1335.             text1 = text1.replace('\\', '')
  1336.             text2 = text2.replace('\\', '')
  1337.             None if format == 'summary' else trailing_space
  1338.             if format in ('heading', 'header'):
  1339.                 log.info(log.bold(text1))
  1340.                 continue
  1341.             None if format in ('option', 'example') else text1.startswith(' ')
  1342.             if format == 'space':
  1343.                 log.info('')
  1344.                 continue
  1345.         
  1346.         log.info('')
  1347.     elif typ == 'rest':
  1348.         (opt_colwidth1, opt_colwidth2) = (0, 0)
  1349.         (exmpl_colwidth1, exmpl_colwidth2) = (0, 0)
  1350.         (note_colwidth1, note_colwidth2) = (0, 0)
  1351.         for line in text_list:
  1352.             (text1, text2, format, trailing_space) = line
  1353.             if format == 'option':
  1354.                 opt_colwidth1 = max(len(text1), opt_colwidth1)
  1355.                 opt_colwidth2 = max(len(text2), opt_colwidth2)
  1356.                 continue
  1357.             if format == 'example':
  1358.                 exmpl_colwidth1 = max(len(text1), exmpl_colwidth1)
  1359.                 exmpl_colwidth2 = max(len(text2), exmpl_colwidth2)
  1360.                 continue
  1361.             if format == 'note':
  1362.                 note_colwidth1 = max(len(text1), note_colwidth1)
  1363.                 note_colwidth2 = max(len(text2), note_colwidth2)
  1364.                 continue
  1365.         
  1366.         opt_colwidth1 += 4
  1367.         opt_colwidth2 += 4
  1368.         exmpl_colwidth1 += 4
  1369.         exmpl_colwidth2 += 4
  1370.         note_colwidth1 += 4
  1371.         note_colwidth2 += 4
  1372.         opt_tablewidth = opt_colwidth1 + opt_colwidth2
  1373.         exmpl_tablewidth = exmpl_colwidth1 + exmpl_colwidth2
  1374.         note_tablewidth = note_colwidth1 + note_colwidth2
  1375.         log.info('restindex\npage-title: %s\ncrumb: %s\nformat: rest\nfile-extension: html\nencoding: utf8\n/restindex\n' % (title, crumb))
  1376.         t = '%s: %s (ver. %s)' % (crumb, title, version)
  1377.         log.info(t)
  1378.         log.info('=' * len(t))
  1379.         log.info('')
  1380.         links = []
  1381.         needs_header = False
  1382.         for line in text_list:
  1383.             (text1, text2, format, trailing_space) = line
  1384.             if format == 'seealso':
  1385.                 links.append(text1)
  1386.                 text1 = '`%s`_' % text1
  1387.             
  1388.             len1 = len(text1)
  1389.             len2 = len(text2)
  1390.             if format == 'summary':
  1391.                 log.info(''.join([
  1392.                     '**',
  1393.                     text1,
  1394.                     '**']))
  1395.                 log.info('')
  1396.                 continue
  1397.             if format in ('para', 'name'):
  1398.                 log.info('')
  1399.                 log.info(text1)
  1400.                 log.info('')
  1401.                 continue
  1402.             if format in ('heading', 'header'):
  1403.                 log.info('')
  1404.                 log.info('**' + text1 + '**')
  1405.                 log.info('')
  1406.                 needs_header = True
  1407.                 continue
  1408.             if format == 'option':
  1409.                 if needs_header:
  1410.                     log.info('.. class:: borderless')
  1411.                     log.info('')
  1412.                     log.info(''.join([
  1413.                         '+',
  1414.                         '-' * opt_colwidth1,
  1415.                         '+',
  1416.                         '-' * opt_colwidth2,
  1417.                         '+']))
  1418.                     needs_header = False
  1419.                 
  1420.                 if text1 and '`_' not in text1:
  1421.                     log.info(''.join([
  1422.                         '| *',
  1423.                         text1,
  1424.                         '*',
  1425.                         ' ' * (opt_colwidth1 - len1 - 3),
  1426.                         '|',
  1427.                         text2,
  1428.                         ' ' * (opt_colwidth2 - len2),
  1429.                         '|']))
  1430.                 elif text1:
  1431.                     log.info(''.join([
  1432.                         '|',
  1433.                         text1,
  1434.                         ' ' * (opt_colwidth1 - len1),
  1435.                         '|',
  1436.                         text2,
  1437.                         ' ' * (opt_colwidth2 - len2),
  1438.                         '|']))
  1439.                 else:
  1440.                     log.info(''.join([
  1441.                         '|',
  1442.                         ' ' * opt_colwidth1,
  1443.                         '|',
  1444.                         text2,
  1445.                         ' ' * (opt_colwidth2 - len2),
  1446.                         '|']))
  1447.                 log.info(''.join([
  1448.                     '+',
  1449.                     '-' * opt_colwidth1,
  1450.                     '+',
  1451.                     '-' * opt_colwidth2,
  1452.                     '+']))
  1453.                 continue
  1454.             None if format == 'example' else '`_' not in text1
  1455.             if format == 'note':
  1456.                 if needs_header:
  1457.                     log.info('.. class:: borderless')
  1458.                     log.info('')
  1459.                     log.info(''.join([
  1460.                         '+',
  1461.                         '-' * note_colwidth1,
  1462.                         '+',
  1463.                         '-' * note_colwidth2,
  1464.                         '+']))
  1465.                     needs_header = False
  1466.                 
  1467.                 if text1.startswith(' '):
  1468.                     log.info(''.join([
  1469.                         '|',
  1470.                         ' ' * (note_tablewidth + 1),
  1471.                         '|']))
  1472.                 
  1473.                 log.info(''.join([
  1474.                     '|',
  1475.                     text1,
  1476.                     ' ' * ((note_tablewidth - len1) + 1),
  1477.                     '|']))
  1478.                 log.info(''.join([
  1479.                     '+',
  1480.                     '-' * note_colwidth1,
  1481.                     '+',
  1482.                     '-' * note_colwidth2,
  1483.                     '+']))
  1484.                 continue
  1485.             if format == 'space':
  1486.                 log.info('')
  1487.                 continue
  1488.         
  1489.         for l in links:
  1490.             log.info('\n.. _`%s`: %s.html\n' % (l, l.replace('hp-', '')))
  1491.         
  1492.         log.info('')
  1493.     elif typ == 'man':
  1494.         log.info('.TH "%s" 1 "%s" Linux "User Manuals"' % (crumb, version))
  1495.         log.info('.SH NAME\n%s \\- %s' % (crumb, title))
  1496.         for line in text_list:
  1497.             (text1, text2, format, trailing_space) = line
  1498.             text1 = text1.replace('\\*', '*')
  1499.             text2 = text2.replace('\\*', '*')
  1500.             len1 = len(text1)
  1501.             len2 = len(text2)
  1502.             if format == 'summary':
  1503.                 log.info('.SH SYNOPSIS')
  1504.                 log.info('.B %s' % text1.replace('Usage:', ''))
  1505.                 continue
  1506.             None if format == 'name' else text1
  1507.             if format in ('header', 'heading'):
  1508.                 log.info('.SH %s' % text1.upper().replace(':', '').replace('[', '').replace(']', ''))
  1509.                 continue
  1510.             if format in 'seealso, para':
  1511.                 log.info(text1)
  1512.                 continue
  1513.         
  1514.         log.info('.SH AUTHOR')
  1515.         log.info('HPLIP (Hewlett-Packard Linux Imaging and Printing) is an')
  1516.         log.info('HP developed solution for printing, scanning, and faxing with')
  1517.         log.info('HP inkjet and laser based printers in Linux.')
  1518.         log.info('.SH REPORTING BUGS')
  1519.         log.info('The HPLIP Launchpad.net site')
  1520.         log.info('.B https://launchpad.net/hplip')
  1521.         log.info('is available to get help, report')
  1522.         log.info('bugs, make suggestions, discuss the HPLIP project or otherwise')
  1523.         log.info('contact the HPLIP Team.')
  1524.         log.info('.SH COPYRIGHT')
  1525.         log.info('Copyright (c) 2001-9 Hewlett-Packard Development Company, L.P.')
  1526.         log.info('.LP')
  1527.         log.info('This software comes with ABSOLUTELY NO WARRANTY.')
  1528.         log.info('This is free software, and you are welcome to distribute it')
  1529.         log.info('under certain conditions. See COPYING file for more details.')
  1530.         log.info('')
  1531.     
  1532.  
  1533.  
  1534. def log_title(program_name, version, show_ver = True):
  1535.     log.info('')
  1536.     if show_ver:
  1537.         log.info(log.bold('HP Linux Imaging and Printing System (ver. %s)' % prop.version))
  1538.     else:
  1539.         log.info(log.bold('HP Linux Imaging and Printing System'))
  1540.     log.info(log.bold('%s ver. %s' % (program_name, version)))
  1541.     log.info('')
  1542.     log.info('Copyright (c) 2001-9 Hewlett-Packard Development Company, LP')
  1543.     log.info('This software comes with ABSOLUTELY NO WARRANTY.')
  1544.     log.info('This is free software, and you are welcome to distribute it')
  1545.     log.info('under certain conditions. See COPYING file for more details.')
  1546.     log.info('')
  1547.  
  1548.  
  1549. def ireplace(old, search, replace):
  1550.     regex = '(?i)' + re.escape(search)
  1551.     return re.sub(regex, replace, old)
  1552.  
  1553.  
  1554. def su_sudo():
  1555.     su_sudo_str = None
  1556.     if which('kdesu'):
  1557.         su_sudo_str = 'kdesu -- %s'
  1558.     elif utils.which('/usr/lib/kde4/libexec/kdesu'):
  1559.         su_sudo_str = '/usr/lib/kde4/libexec/kdesu -- %s'
  1560.     elif utils.which('kdesudo'):
  1561.         su_sudo_str = 'kdesudo -- %s'
  1562.     elif which('gnomesu'):
  1563.         su_sudo_str = 'gnomesu -c "%s"'
  1564.     elif which('gksu'):
  1565.         su_sudo_str = 'gksu "%s"'
  1566.     
  1567.     return su_sudo_str
  1568.  
  1569.  
  1570. def unescape(text):
  1571.     
  1572.     def fixup(m):
  1573.         text = m.group(0)
  1574.         if text[:2] == '&#':
  1575.             
  1576.             try:
  1577.                 if text[:3] == '&#x':
  1578.                     return chr(int(text[3:-1], 16))
  1579.                 return chr(int(text[2:-1]))
  1580.             except ValueError:
  1581.                 pass
  1582.             except:
  1583.                 None<EXCEPTION MATCH>ValueError
  1584.             
  1585.  
  1586.         None<EXCEPTION MATCH>ValueError
  1587.         
  1588.         try:
  1589.             text = chr(htmlentitydefs.name2codepoint[text[1:-1]])
  1590.         except KeyError:
  1591.             pass
  1592.  
  1593.         return text
  1594.  
  1595.     return re.sub('&#?\\w+;', fixup, text)
  1596.  
  1597.  
  1598. def escape(s):
  1599.     if not isinstance(s, unicode):
  1600.         s = unicode(s)
  1601.     
  1602.     s = s.replace(u'&', u'&')
  1603.     for c in htmlentitydefs.codepoint2name:
  1604.         if c != 38:
  1605.             s = s.replace(unichr(c), u'&%s;' % htmlentitydefs.codepoint2name[c])
  1606.             continue
  1607.     
  1608.     for c in range(32) + range(127, 160):
  1609.         s = s.replace(unichr(c), u'&#%d;' % c)
  1610.     
  1611.     return s
  1612.  
  1613.